package core.swarm;

import sun.reflect.generics.reflectiveObjects.NotImplementedException;
import utility.Utils;
import core.Mode;
import core.genetic.Individual;
import core.genetic.Population;

public class Optimizer {
	public void run(Population pop) {
		contSwarm(pop);
	}

	public void binSwarm(Population pop) {
		double[] values = Mode.mode.evaluation.evaluate(pop);
		Individual pid = pop.get(0);
		int best = 0;
		for (int i = 1; i < values.length; i++)
			if (values[i] < values[best])
				best = i;
		pid = pop.get(best);

		for (int i = 0; i < pop.size(); i++) {
			int[] neighbours = new int[4];
			neighbours[0] = (i - 2 + pop.size()) % pop.size();
			neighbours[1] = (i - 1 + pop.size()) % pop.size();
			neighbours[2] = (i + 1) % pop.size();
			neighbours[3] = (i + 2) % pop.size();
			int nbest = 0;
			for (int k = 1; k < neighbours.length; k++)
				if (values[neighbours[nbest]] < values[neighbours[k]])
					nbest = k;
			Individual pgd = pop.get(neighbours[nbest]);

			double r1 = Utils.random.nextDouble() * 4;
			double r2 = 4 - r1;
			Individual ind = pop.get(i);
			for (int d = 0; d < ind.getLength(); d++) {
				// racunanje verovatnoce promene izbora
				// double
				// v=V[i,d]+r1*(pid.getGene(d)-ind.getGene(d))+r2*(pgd.getGene(d)-ind.getGene(d));
			}
		}
		throw new NotImplementedException();

	}

	/**
	 * Continuous particle swarm optimizer with maximum velocity.
	 * 
	 * @param pop
	 */
	public void contSwarm(Population pop) {
		int dimensions = pop.get(0).getLength();
		int n = pop.size();
		int numIter =  Mode.mode.nbGenerations;
		double Vmax = 4;

		double[] bestSoFar =  Mode.mode.evaluation.evaluate(pop);
		Population Pid = pop;
		double[][] v = new double[pop.size()][dimensions];

		for (int gen = 0; gen < numIter; gen++) {
			double[] fitness =  Mode.mode.evaluation.evaluate(pop);
			for (int i = 0; i < n; i++) {
				if (fitness[i] > bestSoFar[i])
					for (int d = 0; d < dimensions; d++)
						Pid.get(i).set(pop.get(i));
				int g = i;
				if (bestSoFar[(i + 1) % bestSoFar.length] > bestSoFar[i])
					g = (i + 1) % bestSoFar.length;
				else if (bestSoFar[(i - 1 + bestSoFar.length)
						% bestSoFar.length] > bestSoFar[i])
					g = (i - 1 + bestSoFar.length) % bestSoFar.length;

				for (int d = 0; d < dimensions; d++) {
					double fi1 = Utils.random.nextDouble() * 4;
					double fi2 = 4 - fi1;
					v[i][d] = v[i][d] + fi1
							* (Pid.get(i).getGene(d) - pop.get(i).getGene(d))
							+ fi2
							* (Pid.get(g).getGene(d) - pop.get(i).getGene(d));
					v[i][d] = (v[i][d] + Vmax / 2) % Vmax;
					pop.get(i).setGene(d, pop.get(i).getGene(d) + v[i][d]);
				}
			}
		}
	}
	
	
}
